<template>
  <ul :class="classes" :style="styles"><slot></slot></ul>
</template>

<script>
import Config from '../../config'
import { oneOf, findComponentsDownward, findComponentsUpward } from '../../utils/assist'
import Emitter from '../../mixins/emitter'
const prefixCls = `${Config.clsPrefix}menu`
export default {
  name: `${Config.namePrefix}Menu`,
  mixins: [ Emitter ],
  props: {
    mode: {
      validator (value) {
        return oneOf(value, ['horizontal', 'vertical'])
      },
      default: 'vertical'
    },
    theme: {
      validator (value) {
        return oneOf(value, ['light', 'dark', 'primary'])
      },
      default: 'light'
    },
    activeName: {
      type: [String, Number]
    },
    openNames: {
      type: Array,
      default () {
        return []
      }
    },
    accordion: {
      type: Boolean,
      default: false
    },
    width: {
      type: String,
      default: '240px'
    }
  },
  data () {
    return {
      currentActiveName: this.activeName,
      openedNames: []
    }
  },
  computed: {
    classes () {
      return [
        `${prefixCls}`,
        `${prefixCls}-${this.theme}`,
        {
          [`${prefixCls}-${this.mode}`]: this.mode
        }
      ]
    },
    styles () {
      let style = {}
      if (this.mode === 'vertical') style.width = this.width
      return style
    }
  },
  methods: {
    updateActiveName () {
      if (this.currentActiveName === undefined) {
        this.currentActiveName = -1
      }
      this.broadcast(`${Config.namePrefix}Submenu`, 'on-update-active-name', false)
      this.broadcast(`${Config.namePrefix}MenuItem`, 'on-update-active-name', this.currentActiveName)
    },
    updateOpenKeys (name) {
      let names = [...this.openedNames]
      const index = names.indexOf(name)
      if (this.accordion) {
        findComponentsDownward(this, `${Config.namePrefix}Submenu`).forEach(item => {
          item.opened = false
        })
      }
      if (index >= 0) {
        let currentSubmenu = null
        findComponentsDownward(this, `${Config.namePrefix}Submenu`).forEach(item => {
          if (item.name === name) {
            currentSubmenu = item
            item.opened = false
          }
        })
        findComponentsUpward(currentSubmenu, `${Config.namePrefix}Submenu`).forEach(item => {
          item.opened = true
        })
        findComponentsDownward(currentSubmenu, `${Config.namePrefix}Submenu`).forEach(item => {
          item.opened = false
        })
      } else {
        if (this.accordion) {
          let currentSubmenu = null
          findComponentsDownward(this, `${Config.namePrefix}Submenu`).forEach(item => {
            if (item.name === name) {
              currentSubmenu = item
              item.opened = true
            }
          })
          findComponentsUpward(currentSubmenu, `${Config.namePrefix}Submenu`).forEach(item => {
            item.opened = true
          })
        } else {
          findComponentsDownward(this, `${Config.namePrefix}Submenu`).forEach(item => {
            if (item.name === name) item.opened = true
          })
        }
      }
      let openedNames = findComponentsDownward(this, `${Config.namePrefix}Submenu`).filter(item => item.opened).map(item => item.name)
      this.openedNames = [...openedNames]
      this.$emit('on-open-change', openedNames)
    },
    updateOpened () {
      const items = findComponentsDownward(this, `${Config.namePrefix}Submenu`)
      if (items.length) {
        items.forEach(item => {
          if (this.openedNames.indexOf(item.name) > -1) item.opened = true
          else item.opened = false
        })
      }
    }
  },
  mounted () {
    this.updateActiveName()
    this.openedNames = [...this.openNames]
    this.updateOpened()
    this.$on('on-menu-item-select', (name) => {
      this.currentActiveName = name
      this.$emit('on-select', name)
    })
  },
  watch: {
    openNames (names) {
      this.openedNames = names
    },
    activeName (val) {
      this.currentActiveName = val
    },
    currentActiveName () {
      this.updateActiveName()
    }
  }
}
</script>
